#include "gpxmanager.h"

GpxManager::GpxManager()
{}

GpxManager::~GpxManager()
{}

void GpxManager::write(QList <Point> points, QList <Route> routes, QList <Track> tracks, QList <Map> maps)
{
    QDomDocument *doc = new QDomDocument("xml");
    QDomElement gpx = doc->createElement("gpx");
    gpx.setAttribute("xmlns:xsi", "http://www.w3.org/2010/XMLSchema-instance");
    gpx.setAttribute("xmlns:xsd", "http://www.w3.org/2001/XMLSchema");
    gpx.setAttribute("version", "1.1");
    gpx.setAttribute("creator", "geocaching-gwc");
    gpx.setAttribute("xsi:schemaLocation", "http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd");
    gpx.setAttribute("xmlns", "http://www.topografix.com/GPX/1/1");
    QDomElement name = doc->createElement("name");
    name.appendChild(doc->createTextNode("New Query"));
    gpx.appendChild(name);
    QDomElement desc = doc->createElement("desc");
    desc.appendChild(doc->createTextNode("Geocaching file modified by geocaching-gwc"));
    gpx.appendChild(desc);
    QTime current_time = QTime::currentTime();
    QDomElement time = doc->createElement("time");
    time.appendChild(doc->createTextNode(current_time.toString(Qt::ISODate).append(".").append(current_time.msec())));
    gpx.appendChild(time);

    foreach(Map m, maps)
    {
        gpx.appendChild(map2gpx(doc,m));
    }

    foreach(Point p, points)
    {
        gpx.appendChild(point2gpx(doc,p));
    }

    foreach(Route r, routes)
    {
        gpx.appendChild(route2gpx(doc,r));
    }

    foreach(Track t, tracks)
    {
        gpx.appendChild(track2gpx(doc,t));
    }

    doc->appendChild(gpx);
    QFile file("my.xml");
        if(file.open(QIODevice::WriteOnly))
        {
            QTextStream(&file) << doc->toString();
            file.close();
        }
}

void GpxManager::read(QList <Point> &points,QList <Map> &maps)
{
    QFile file("my.xml");
    file.open(QIODevice::ReadOnly);
    QDomDocument gpxfile;
    gpxfile.setContent(&file);
    file.close();
    QDomElement gpxelement = gpxfile.documentElement();
    QDomNodeList wpt_list = gpxelement.elementsByTagName("point");
    QDomNodeList m_list = gpxelement.elementsByTagName("map");
    QDomNodeList r_list = gpxelement.elementsByTagName("route");
    Point p;
    Map m;
    Route r;
    //map
    for (int m_i = 0; m_i < m_list.count(); ++m_i)
    {
        QDomElement m_element = m_list.item(m_i).toElement();
        QDomNode mnode;
        GeoCoordinates tlp, trp, brp, blp;
        mnode = m_element.elementsByTagName("id").item(0).firstChild();
        if (!mnode.isNull())
            m.SetID(mnode.nodeValue().toULong());
        mnode = m_element.elementsByTagName("name").item(0).firstChild();
        if (!mnode.isNull())
            m.SetName(mnode.nodeValue());
        mnode = m_element.elementsByTagName("filePath").item(0).firstChild();
        if (!mnode.isNull())
            m.SetFilePath(mnode.nodeValue());

        mnode = m_element.elementsByTagName("tlplat").item(0).firstChild();
        if (!mnode.isNull())
            tlp.SetLatitude(mnode.nodeValue().toDouble());
        mnode = m_element.elementsByTagName("tlplon").item(0).firstChild();
        if (!mnode.isNull())
            tlp.SetLongitude(mnode.nodeValue().toDouble());

        mnode = m_element.elementsByTagName("trplat").item(0).firstChild();
        if (!mnode.isNull())
            trp.SetLatitude(mnode.nodeValue().toDouble());
        mnode = m_element.elementsByTagName("trplon").item(0).firstChild();
        if (!mnode.isNull())
            trp.SetLongitude(mnode.nodeValue().toDouble());

        mnode = m_element.elementsByTagName("brplat").item(0).firstChild();
        if (!mnode.isNull())
            brp.SetLatitude(mnode.nodeValue().toDouble());
        mnode = m_element.elementsByTagName("brplon").item(0).firstChild();
        if (!mnode.isNull())
            brp.SetLongitude(mnode.nodeValue().toDouble());

        mnode = m_element.elementsByTagName("blplat").item(0).firstChild();
        if (!mnode.isNull())
            blp.SetLatitude(mnode.nodeValue().toDouble());
        mnode = m_element.elementsByTagName("blplon").item(0).firstChild();
        if (!mnode.isNull())
            blp.SetLongitude(mnode.nodeValue().toDouble());
        m.SetCalibration(tlp, trp, brp, blp);

        maps.push_back(m);
    }
    //map
    /*
    foreach(Point pl, plist)
    {
        QDomNode node;
        node = wpt_element.elementsByTagName("id").item(0).firstChild();
        if (!node.isNull())
            pl->setTime(node.nodeValue());
        pl.SetID(gpxelement.);
    }
    */
    //point
    for (int wpt_i = 0; wpt_i < wpt_list.count(); ++wpt_i)
    {
        QDomElement wpt_element = wpt_list.item(wpt_i).toElement();
        QDomNode node;
        GeoCoordinates coord;
        node = wpt_element.elementsByTagName("id").item(0).firstChild();
        if (!node.isNull())
            p.SetID(node.nodeValue().toULong());
        node = wpt_element.elementsByTagName("name").item(0).firstChild();
        if (!node.isNull())
            p.SetName(node.nodeValue());
        node = wpt_element.elementsByTagName("lat").item(0).firstChild();
        if (!node.isNull())
            coord.SetLatitude(node.nodeValue().toDouble());
        node = wpt_element.elementsByTagName("lon").item(0).firstChild();
        if (!node.isNull())
            coord.SetLongitude(node.nodeValue().toDouble());
        p.SetCoordinates(coord);

        QDomNodeList f_list;

        /*
        f_list = wpt_element.elementsByTagName("files");
        QDomElement ft_element = f_list.item(wpt_i).toElement();
        QDomNodeList p_list = ft_element.elementsByTagName("path");
        for (int p_i = 0; p_i < p_list.count(); ++p_i)
        {
            QDomNode pnode = p_list.item(p_i).firstChild();
            if (!pnode.isNull())
                p.AddFile(pnode.nodeValue());
        }
        */

        f_list = wpt_element.elementsByTagName("path");
        for (int f_i = 0; f_i < f_list.count(); ++f_i)
        {
            QDomNode fnode = f_list.item(f_i).firstChild();
            if (!fnode.isNull())
                p.AddFile(fnode.nodeValue());
        }
        points.push_back(p);
    }
    //point
/*
    //route
    for (int r_i = 0; r_i < r_list.count(); ++r_i)
    {
        QDomElement r_element = r_list.item(r_i).toElement();
        QDomNode rnode;
        rnode = r_element.elementsByTagName("id").item(0).firstChild();
        if (!rnode.isNull())
            r.SetID(rnode.nodeValue().toULong());

        rnode = r_element.elementsByTagName("name").item(0).firstChild();
        if (!rnode.isNull())
            r.SetName(rnode.nodeValue());
        //rnode = r_element.elementsByTagName("files").item(r_i).toElement();
        QDomNodeList rf_list = r_element.elementsByTagName("path");
        for (int rf_i = 0+pcount; rf_i < rf_list.count(); ++rf_i)
        {
            QDomNode rfnode = rf_list.item(rf_i).firstChild();
            if (!rfnode.isNull())
            {
                r.AddFile(rfnode.nodeValue());
                pcount=rf_i;
            }
        }
    }
    //route
  */
}

QDomElement GpxManager::point2gpx(QDomDocument *doc, Point point)
{
    QDomElement el = doc->createElement("point");
    el.appendChild(createTextElement(doc,"id",QString::number(point.GetID())));
    el.appendChild(createTextElement(doc,"name",point.GetName()));
    el.appendChild(createTextElement(doc,"lat",QString::number(point.GetCoordinates().GetLatitude(),'g',9)));
    el.appendChild(createTextElement(doc,"lon",QString::number(point.GetCoordinates().GetLongitude(),'g',9)));
    if (point.GetFileList().count()>0)
    {
        QDomElement files = doc->createElement("files");
        foreach(QString fpath,point.GetFileList())
        {
            files.appendChild(createTextElement(doc,"path",fpath));
        }
        el.appendChild(files);
    }
    return el;
}

QDomElement GpxManager::route2gpx(QDomDocument *doc, Route route)
{
    QDomElement el = doc->createElement("route");
    el.appendChild(createTextElement(doc,"id",QString::number(route.GetID())));
    el.appendChild(createTextElement(doc,"name",route.GetName()));
    QDomElement points = doc->createElement("points");
    foreach(unsigned long idpoint,route.GetPointList())
    {
        points.appendChild(createTextElement(doc,"idpoint",QString::number(idpoint)));
    }
    el.appendChild(points);

    QDomElement files = doc->createElement("files");
    foreach(QString fpath,route.GetFileList())
    {
        files.appendChild(createTextElement(doc,"path",fpath));
    }
    el.appendChild(files);
    return el;
}

QDomElement GpxManager::track2gpx(QDomDocument *doc, Track track)
{
    QDomElement el = doc->createElement("track");
    el.appendChild(createTextElement(doc,"id",QString::number(track.GetID())));
    el.appendChild(createTextElement(doc,"name",track.GetName()));
    QDomElement points = doc->createElement("points");
    foreach(TrackPoint idpoint,track.GetPointList())
    {
        QDomElement tpoint = doc->createElement("tpoint");
        points.appendChild(createTextElement(doc,"lat",QString::number(idpoint.GetCoordinates().GetLatitude(),'g',9)));
        points.appendChild(createTextElement(doc,"lon",QString::number(idpoint.GetCoordinates().GetLongitude(),'g',9)));
        points.appendChild(createTextElement(doc,"time",idpoint.GetDateTime().toString()));
        tpoint.appendChild(points);
    }
    el.appendChild(points);

    return el;
}

QDomElement GpxManager::map2gpx(QDomDocument *doc, Map map)
{
    GeoCoordinates tlp, trp, brp, blp;
    map.GetCalibration(tlp, trp, brp, blp);
    QDomElement el = doc->createElement("map");
    el.appendChild(createTextElement(doc,"id",QString::number(map.GetID())));
    el.appendChild(createTextElement(doc,"name",map.GetName()));
    el.appendChild(createTextElement(doc,"filePath",map.GetFilePath()));
    el.appendChild(createTextElement(doc,"tlplat",QString::number(tlp.GetLatitude(),'g',9)));
    el.appendChild(createTextElement(doc,"tlplon",QString::number(tlp.GetLongitude(),'g',9)));

    el.appendChild(createTextElement(doc,"trplat",QString::number(trp.GetLatitude(),'g',9)));
    el.appendChild(createTextElement(doc,"trplon",QString::number(trp.GetLongitude(),'g',9)));

    el.appendChild(createTextElement(doc,"brplat",QString::number(brp.GetLatitude(),'g',9)));
    el.appendChild(createTextElement(doc,"brplon",QString::number(brp.GetLongitude(),'g',9)));

    el.appendChild(createTextElement(doc,"blplat",QString::number(blp.GetLatitude(),'g',9)));
    el.appendChild(createTextElement(doc,"blplon",QString::number(blp.GetLongitude(),'g',9)));
    return el;
}

QDomElement GpxManager::createTextElement(QDomDocument *doc, QString name, QString value)
{
    QDomElement e = doc->createElement(name);
    e.appendChild(doc->createTextNode(value));
    return e;
}
